package com.hcc.gateway.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hcc.gateway.dao.mapper.ApiParamMappingDao;
import com.hcc.gateway.domain.enums.ApiParamMappingTypeEnum;
import com.hcc.gateway.domain.po.ApiParamMappingPo;
import com.hcc.gateway.domain.vo.ApiParamMappingVo;
import com.hcc.gateway.service.ApiParamMappingService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ApiParamMappingServiceImpl
 *
 * @author hushengjun
 * @date 2022/1/17
 */
@Service
public class ApiParamMappingServiceImpl extends ServiceImpl<ApiParamMappingDao, ApiParamMappingPo> implements ApiParamMappingService {

    @Override
    public void saveApiParamMapping(ApiParamMappingVo root) {
        ApiParamMappingPo paramPo = new ApiParamMappingPo();
        BeanUtils.copyProperties(root, paramPo, "children");
        if (paramPo.getRequired() == null) {
            paramPo.setRequired(false);
        }
        paramPo.setId(null);
        this.save(paramPo);

        for (ApiParamMappingVo child : root.getChildren()) {
            child.setApiConfig(root.getApiConfig());
            child.setParentId(paramPo.getId());
            child.setType(root.getType());
            this.saveApiParamMapping(child);
        }
    }

    @Override
    public ApiParamMappingVo findApiParamMappingByApiConfig(Long apiConfig, ApiParamMappingTypeEnum type) {
        LambdaQueryWrapper<ApiParamMappingPo> queryWrapper = Wrappers.<ApiParamMappingPo>lambdaQuery()
                .eq(ApiParamMappingPo::getApiConfig, apiConfig)
                .eq(ApiParamMappingPo::getType, type.name());
        List<ApiParamMappingPo> apiReqParamPos = this.list(queryWrapper);
        if (CollectionUtil.isEmpty(apiReqParamPos)) {
            return null;
        }

        ApiParamMappingPo root = null;
        Map<Long, List<ApiParamMappingPo>> childMap = new HashMap<>();
        for (ApiParamMappingPo apiParamMappingPo : apiReqParamPos) {
            if (apiParamMappingPo.getParentId() == null) {
                root = apiParamMappingPo;
            } else {
                List<ApiParamMappingPo> children = childMap.get(apiParamMappingPo.getParentId());
                if (CollectionUtil.isEmpty(children)) {
                    List<ApiParamMappingPo> tempChildren = new ArrayList<>();
                    tempChildren.add(apiParamMappingPo);
                    childMap.put(apiParamMappingPo.getParentId(), tempChildren);
                } else {
                    children.add(apiParamMappingPo);
                    childMap.put(apiParamMappingPo.getParentId(), children);
                }
            }
        }
        if (root == null) {
            return null;
        }

        ApiParamMappingVo apiParamMappingVo = new ApiParamMappingVo();
        BeanUtils.copyProperties(root, apiParamMappingVo);
        // 构建子节点
        this.buildApiReqParamVo(apiParamMappingVo, childMap);

        return apiParamMappingVo;
    }

    private void buildApiReqParamVo(ApiParamMappingVo apiParamMappingVo, Map<Long, List<ApiParamMappingPo>> childMap) {
        List<ApiParamMappingPo> children = childMap.get(apiParamMappingVo.getId());
        if (CollectionUtil.isEmpty(children)) {
            apiParamMappingVo.setChildren(Collections.emptyList());
            return;
        }
        List<ApiParamMappingVo> tempChildren = new ArrayList<>();
        for (ApiParamMappingPo child : children) {
            ApiParamMappingVo temp = new ApiParamMappingVo();
            BeanUtils.copyProperties(child, temp);
            tempChildren.add(temp);
        }
        apiParamMappingVo.setChildren(tempChildren);
        for (ApiParamMappingVo child : tempChildren) {
            this.buildApiReqParamVo(child, childMap);
        }
    }

}
